/***************************************************
 ** @Desc : This file for 充值
 ** @Time : 2019.04.04 18:01
 ** @Author : Joker
 ** @File : recharge
 ** @Last Modified by : Joker
 ** @Last Modified time: 2019.04.04 18:01
 ** @Software: GoLand
****************************************************/
package controllers

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"net/http"
	"net/url"
	"recharge/models"
	"recharge/sys"
	"recharge/utils"
	"recharge/utils/interface_config"
	"regexp"
	"strconv"
	"strings"
)

type RechargeV2 struct {
	KeepSession
}

var encrypt = utils.Encrypt{}

// 商户充值
// @router /merchant/do_recharge_v2/?:params [post]
func (the *RechargeV2) DoRechargeV2() {
	userId := the.GetSession("userId").(int)

	//channel := the.GetString("channel")
	//merchant := the.GetString("merchant")
	accountNo := strings.TrimSpace(the.GetString("accountNo"))
	accountName := strings.TrimSpace(the.GetString("accountName"))
	certificateNo := strings.TrimSpace(the.GetString("certificateNo"))
	mobileNo := strings.TrimSpace(the.GetString("mobileNo"))
	recevieBank := the.GetString("recevieBank")
	money := strings.TrimSpace(the.GetString("money"))

	var msg = utils.FAILED_STRING
	var flag = utils.FAILED_FLAG

	matched, _ := regexp.MatchString(`^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$`, money)
	if accountNo == "" || accountName == "" || money == "" {
		msg = "银行卡或户名不能为空!"
	} else if !matched {
		msg = "请输入正确的充值金额哦!"
	} else {
		parseFloat, _ := strconv.ParseFloat(money, 64)
		if parseFloat < utils.SingleMinForRecharge {
			msg = "充值金额单笔不能小于20哦!"
		} else {

			XFMerchant := merchantFactor.QueryOneMerchantForRecharge()

			record := models.RechargeRecord{}
			record.UserId = userId
			record.MerchantNo = XFMerchant.MerchantNo

			record.SerialNumber = utils.XF + globalMethod.GetNowTimeV2() + globalMethod.RandomString(10)
			record.ReOrderId = utils.XF + globalMethod.GetNowTimeV2() + globalMethod.RandomString(8)
			record.ReAmount, _ = globalMethod.MoneyYuanToFloat(money)
			record.ReAccountNo = accountNo
			record.ReAccountName = accountName
			record.ReCertificateType = "0"
			record.ReCertificateNo = certificateNo
			record.ReMobileNo = mobileNo
			record.ReRecevieBank = recevieBank

			record.NoticeUrl = interface_config.XF_RECHANGE_NOTICE_URL_V2 + record.ReOrderId

			// 多通道充值
			if strings.Compare(utils.XF, XFMerchant.ChannelType) == 0 {
				//先锋
				record.RecordType = utils.XF

				encode := encrypt.EncodeMd5([]byte(globalMethod.RandomString(32)))
				result, err := xfRechargeV2(record, encode, XFMerchant.SecretKey)
				if err != nil {
					msg = err.Error()
				} else {

					resp := models.XFRechargeResponseBody{}
					err = json.Unmarshal(result, &resp)
					if err != nil {
						sys.LogError("response data format is error:", err)
						msg = "先锋充值响应数据格式错误"
					} else {

						if strings.Compare("00000", resp.ResCode) != 0 {
							sys.LogDebug("先锋充值错误:", resp)
							msg = "先锋充值错误：" + resp.ResMessage
						} else {

							nowTime := globalMethod.GetNowTime()
							record.CreateTime = nowTime
							record.EditTime = nowTime
							record.Remark = resp.ResMessage

							//状态以异步回调为准
							record.Status = utils.I

							// 添加充值记录
							flag, _ = rechargeMdl.InsertRechargeRecord(record)
						}
					}
				}
			}
		}
	}

	the.Data["json"] = globalMethod.JsonFormat(flag, "", msg, "")
	the.ServeJSON()
	the.StopRun()
}

// 先锋道通充值
func xfRechargeV2(record models.RechargeRecord, b, key string) ([]byte, error) {
	// 请求参数
	reqParams := url.Values{}
	reqParams.Add("version", interface_config.VERSION_V2)
	reqParams.Add("service", "REQ_OFFLINE_RECHARGE")
	reqParams.Add("merchantId", record.MerchantNo)
	blockKey, err := merchantImpl.XFHandleBlockKey(b, key)
	if err != nil {
		s := "先锋充值aes秘钥加密失败"
		sys.LogTrace(s, err)
		return nil, errors.New(s)
	}
	reqParams.Add("tm", blockKey)

	// 需要的加密参数
	dataParams := models.XFRechargeData{}
	dataParams.MerchantNo = record.ReOrderId
	fen, _ := globalMethod.MoneyYuanToFen(record.ReAmount)
	dataParams.Amount = fen
	dataParams.TransCur = "156"
	dataParams.AccountNo = record.ReAccountNo
	dataParams.AccountName = record.ReAccountName

	dataParams.RecevieBank = record.ReRecevieBank
	dataParams.NoticeUrl = record.NoticeUrl

	// 加密参数
	dataString, _ := json.Marshal(&dataParams)
	data, err := AES.AesEncryptV2(string(dataString), b)
	if err != nil {
		return nil, err
	}

	reqParams.Add("data", data)

	// 生成签名
	respParams := map[string]string{}
	respParams["service"] = "REQ_OFFLINE_RECHARGE"
	respParams["version"] = interface_config.VERSION_V2
	respParams["merchantId"] = record.MerchantNo
	respParams["data"] = data
	respParams["tm"] = blockKey
	params := globalMethod.ToStringByMap(respParams)

	signBytes, err := merchantImpl.XFGenerateSignV2(params, interface_config.PRIVATE_KEY)
	if err != nil {
		s := "先锋充值生成签名失败"
		sys.LogTrace(s, err)
		return nil, errors.New(s)
	}
	reqParams.Add("sign", string(signBytes))

	// 发送请求
	resp, err := http.PostForm(interface_config.XF_RECHANGE_URL, reqParams)
	if err != nil {
		s := "先锋充值请求失败"
		sys.LogTrace(s, err)
		return nil, errors.New(s)
	}

	// 处理响应
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		s := "先锋充值响应为空"
		sys.LogTrace(s, err)
		return nil, errors.New(s)
	}
	defer resp.Body.Close()

	respData := models.RespData{}
	err = json.Unmarshal(body, &respData)
	if err != nil {
		s := "先锋充值响应数据格式错误"
		sys.LogTrace(s, err)
		return nil, errors.New(s)
	}

	if respData.Data == "" {
		sys.LogInfo("先锋充值响应：", string(body))
		return nil, errors.New("先锋充值响应data为空！")
	}

	s, err := merchantImpl.DecryptRespDataByPrivateKey(respData.Tm)
	bytes, err := AES.AesDecryptV2([]byte(respData.Data), s)
	if err != nil {
		s := "先锋充值响应解密错误"
		sys.LogTrace(s, err)
		return nil, errors.New(s)
	}

	return bytes, err
}
